home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / Z4ZXCP.C < prev    next >
C/C++ Source or Header  |  1993-08-13  |  7KB  |  242 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    z4z5cp.c
  5. //   Title:    ZIP+4 Engine
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //
  24. //    This module contains the compressor for the ZIP4 cross reference file.
  25. //
  26. //    The code in this module should be written entirely in C. 
  27. //    Do not use any C++ constructs.
  28. //
  29. //    This module is portable to:
  30. //        DOS 3.X+
  31. //        MS Windows 3.X+
  32. //        OS/2 2.X+
  33. //        OS/2 2.0 PM
  34. //        SCO UNIX.
  35. //
  36. //    The following compilers are supported:
  37. //        MSC 6.0A
  38. //        MSC/C++ 7.0
  39. //        Borland C++ 3.1 for DOS
  40. //        Borland C++ 1.0 for OS/2 2.X
  41. //        SCO UNIX cc
  42. //
  43. //----------------------------------------------------------------------------
  44. #include <z4.h>
  45.  
  46. //----------------------------------------------------------------------------
  47. //    Prototypes
  48. //----------------------------------------------------------------------------
  49. static BOOL FN_L Z4ZXCompressAppend(PDATACOMP, PZ4_ZX);
  50. static ULONG ulZipPrev;
  51. static RECID recid;
  52.  
  53.  
  54. //----------------------------------------------------------------------------
  55. //   Description:    Compression function    
  56. //    Parameters:    pdatacomp    Compressor data
  57. //       Returns:    Compression function result code. See data.h.
  58. //----------------------------------------------------------------------------
  59. SHORT FN_E Z4ZXCompress(PDATACOMP pdatacomp)
  60. {
  61. static Z4_ZX zx;
  62. static SIZET cMaxRecords;
  63. static BOOL fPending;                        // ZIP5 record pending?
  64. static SIZET cZip;
  65. static SIZET cAddonLo;
  66. static SIZET cAddonHi;
  67.  
  68.     LONG lRec = pdatacomp->dlmrec.lId;
  69.     PPSZ ppsz = pdatacomp->dlmrec.apsz;
  70.     CHAR szAddonLo[MAX_ADDON+1];
  71.     CHAR szAddonHi[MAX_ADDON+1];
  72.     CHAR szZip5[MAX_ZIP5+1];
  73.     CHAR szZip4[MAX_ZIP4+1];
  74.  
  75.     switch (lRec)
  76.         {
  77.         case DAI_INITIALIZE:                    // Initialize at startup
  78.             cMaxRecords = 0;
  79.             Assert(MAX_ZIP4_RECS <= pdatacomp->cbMax / sizeof(RECID));
  80.             cZip = DataField(pdatacomp->dlmrec.pcfg, "zipcode");
  81.             cAddonLo = DataField(pdatacomp->dlmrec.pcfg, "addon_lo");
  82.             cAddonHi = DataField(pdatacomp->dlmrec.pcfg, "addon_hi");
  83.         case DAI_START_BLK:                    // Start block
  84.             ulZipPrev = 0L;
  85.             fPending = FALSE;
  86.             recid.usOffset = 0;
  87.             recid.lBlock = 0;
  88.             return DAO_SUCCESS;
  89.  
  90.         case DAI_TERMINATE:                    // Terminate
  91.             Output("\nMaximum of %u records in a ZIP+4.\n", cMaxRecords);
  92.         case DAI_FAILURE:                        // Failed
  93.         case DAI_END_BLK:                        // End block
  94.             return DAO_SUCCESS;
  95.  
  96.         case DAI_LAST_REC:                    // This should not happen
  97.             if (!fPending)
  98.                 return DAO_FAILURE;
  99.             Z4ZXCompressAppend(pdatacomp, &zx);
  100.             return DAO_FLUSH;
  101.         }
  102.                                                     // Decode
  103.     strb2a((PBYTE)ppsz[cAddonLo], MAX_ADDON_BCD, szAddonLo, MAX_ADDON, TRUE);
  104.     strb2a((PBYTE)ppsz[cAddonHi], MAX_ADDON_BCD, szAddonHi, MAX_ADDON, TRUE);
  105.     strb2a((PBYTE)ppsz[cZip], MAX_ZIP5_BCD, szZip5, MAX_ZIP5, TRUE);
  106.  
  107.     szAddonLo[MAX_ADDON] = '\0';
  108.     szAddonHi[MAX_ADDON] = '\0';
  109.     szZip5[MAX_ZIP5] = '\0';
  110.  
  111.     strcpy(szZip4, szZip5);                    // Build +4 code
  112.     strcat(szZip4, szAddonLo);
  113.  
  114.     if (fPending)
  115.         {
  116.         if (strcmp(zx.szZip5, szZip5) != 0
  117.         || strcmp(zx.szAddonLo, szAddonLo) != 0)
  118.             {
  119.             Z4ZXCompressAppend(pdatacomp, &zx);
  120.             fPending = FALSE;
  121.             return DAO_MARK_FLUSH;
  122.             }
  123.         Assert(zx.cRecords < MAX_ZIP4_RECS);
  124.         if (strcmp(zx.szAddonHi, szAddonHi) < 0)
  125.             strcpy(zx.szAddonHi, szAddonHi);
  126.         zx.arecid[zx.cRecords] = pdatacomp->dlmrec.recid;;
  127.         zx.cRecords++;
  128.         cMaxRecords = MAX(cMaxRecords, zx.cRecords);
  129.         return DAO_NEXT;
  130.         }
  131.     fPending = TRUE;
  132.     memset(&zx, 0, sizeof(zx));
  133.  
  134.     strcpy(zx.szAddonLo, szAddonLo);
  135.     strcpy(zx.szAddonHi,    szAddonHi);
  136.     strcpy(zx.szZip5,        szZip5);
  137.  
  138.     zx.arecid[zx.cRecords] = pdatacomp->dlmrec.recid;;
  139.     zx.cRecords++;
  140.     cMaxRecords = MAX(cMaxRecords, zx.cRecords);
  141.     return DAO_NEXT;
  142. }
  143.  
  144.  
  145. //----------------------------------------------------------------------------
  146. //   Description:    Compress the current ZIP5 record
  147. //    Parameters:    pdatacomp    Compresser data
  148. //                        pz5            ZIP5 record
  149. //       Returns:    TRUE if successful.
  150. //----------------------------------------------------------------------------
  151. static BOOL FN_L Z4ZXCompressAppend(PDATACOMP pdatacomp, PZ4_ZX pzx)
  152. {
  153.     ULONG ulDelta, ulZip;
  154.     BYTE bBuf[sizeof(RECID) * MAX_ZIP4_RECS];
  155.     SIZET cBuf;
  156.     PBYTE pb = pdatacomp->pb;
  157.     CHAR szZip4[MAX_ZIP4+1];
  158.     USHORT usAddonLo, usAddonHi, usDelta;
  159.  
  160.     strcpy(szZip4, pzx->szZip5);            // Build +4 code
  161.     strcat(szZip4, pzx->szAddonLo);
  162.  
  163.     ulZip = (ULONG)atol(szZip4);            // Compute ZIP4 as ulong
  164.     ulDelta = ulZip - ulZipPrev;            // Compute delta from previous
  165.     if (ulZip <= ulZipPrev)
  166.         Output("\nZIP+4: %09lu %09lu\n", ulZip, ulZipPrev);
  167.  
  168.     Assert(ulZip > ulZipPrev);
  169.  
  170.     usAddonLo = (USHORT)atoi(pzx->szAddonLo);
  171.     usAddonHi = (USHORT)atoi(pzx->szAddonHi);
  172.     Assert(usAddonHi >= usAddonLo);
  173.     usDelta = usAddonHi - usAddonLo;
  174.  
  175.     *pb = (BYTE)(ulDelta & 0x0000003FL);
  176.     if (usDelta)
  177.         *pb |= 0x40;                            // Range follows!
  178.  
  179.     if (ulDelta > 63 || ulDelta == 0)    // First byte can not be 0!!
  180.         {
  181.         *pb |= 0x80;                            
  182.         pb++;
  183.         ulDelta >>= 6;
  184.         Assert((ulDelta & 0xFF000000L) == 0);
  185.  
  186.         *pb++ = (BYTE)(ulDelta & 0x000000FFL);
  187.         ulDelta >>= 8;
  188.         *pb++ = (BYTE)(ulDelta & 0x000000FFL);
  189.         ulDelta >>= 8;
  190.         *pb++ = (BYTE)(ulDelta & 0x000000FFL);
  191.         }
  192.     else
  193.         pb++;
  194.  
  195.     if (usDelta)                                // Encode range delta
  196.         {
  197.         usDelta--;
  198.        *pb = (BYTE)(usDelta & 0x007F);
  199.        if (usDelta > 0x007F)
  200.            {
  201.            *pb |= 0x80;
  202.            pb++;
  203.            Assert((usDelta >> 7) < 256);
  204.            *pb = (BYTE)usDelta;
  205.            pb++;
  206.            }
  207.        else
  208.            pb++;
  209.         }
  210.                                                     // Encode record ids
  211.     if (!RecIdEncode(pzx->arecid, pzx->cRecords, bBuf, sizeof(bBuf), &cBuf, &recid))
  212.         return FALSE;
  213.  
  214.     Assert(cBuf);                                // Encode byte count
  215.     cBuf--;
  216.     *pb = (BYTE)(cBuf & 0x007F);
  217.     if (cBuf > 0x007F)
  218.         {
  219.         *pb |= 0x80;
  220.         pb++;
  221.         Assert((cBuf >> 7) < 256);
  222.         *pb = (BYTE)cBuf;
  223.         pb++;
  224.         }
  225.     else
  226.         pb++;
  227.  
  228.     cBuf++;
  229.     Assert(pdatacomp->cb <= pdatacomp->cbMax);
  230.     Assert(cBuf + 10 < pdatacomp->cbMax - pdatacomp->cb);
  231.     memcpy(pb, bBuf, cBuf);                    // Copy encoded record ids to output
  232.     pb += cBuf;
  233.  
  234.     ulZipPrev = ulZip;
  235.     pdatacomp->cb = (SIZET)(pb - pdatacomp->pb);
  236.     return TRUE;
  237. }
  238. //----------------------------------------------------------------------------
  239. //------------------------------- End of File --------------------------------
  240. //----------------------------------------------------------------------------
  241.  
  242.